package com.liuyi.netty.im.test.im.client;

import com.liuyi.netty.im.commons.codes.CodeConst;
import com.liuyi.netty.im.commons.codes.LimCodeDecoder;
import com.liuyi.netty.im.commons.codes.LimCodeEncode;
import com.liuyi.netty.im.test.im.method.ImSdkMethod;
import com.liuyi.netty.im.test.util.ImHelp;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * 客户端服务
 *
 * @author Mr.Fmy
 * @since 2022/1/19
 */
@Slf4j
public class ClientServer {

    private final String host;
    private final int port;
    private static EventLoopGroup workerGroup = new NioEventLoopGroup(4);
    @Getter
    private Channel channel;

    public ClientServer(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void start() throws InterruptedException {
        this.clientServer();
    }

    public void shutdown() {
        if (this.channel != null) {
            this.channel.close();
        }
    }

    public boolean login(String userId) {
        if (!getReady() && channel != null) {
            ImSdkMethod.login(channel, userId);
            return true;
        }
        return false;
    }

    public boolean logout() {
        if (getReady()) {
            ImSdkMethod.logout(channel);
            return true;
        }
        return false;
    }

    protected void clientServer() throws InterruptedException {
        Bootstrap b = new Bootstrap(); // (1)
        b.group(workerGroup); // (2)
        b.channel(NioSocketChannel.class); // (3)
        b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
        b.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                //心跳保持器
                pipeline.addLast(new HeartbeatHanlder(0L, 30L, ImHelp.getJsonProtocol(CodeConst.Command.HEARTBEAT, null)));
                //解码器
                pipeline.addLast(new LimCodeDecoder());
                //编码器
                pipeline.addLast(new LimCodeEncode());
                //自定义协议处理器
                pipeline.addLast(new ClientSdkHandler());
            }
        });
        // Start the client.
        ChannelFuture sync = b.connect(host, port).sync();
        this.channel = sync.channel();
    }

    public boolean getReady() {
        if (channel != null && channel.isOpen()) {
            return ChannelStorage.getReady(channel.id());
        }
        return false;
    }

    public void sendMessage(int qps,ClientServer toServes) {
        String fromId = ChannelStorage.getUserInfo(this.getChannel().id());
        String toId = ChannelStorage.getUserInfo(toServes.getChannel().id());
        ImSdkMethod.sendMessage(qps,fromId,ImHelp.sessionId(CodeConst.SessionType.C2C, toId));
    }
}
